package edu.towson.forensics;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;

import android.app.ActivityManager;
import android.app.Service;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class LogMonitor extends Service{
	private CollectLogTask mCollectLogTask;
	public static final String[] toCatch = {"susteen", "datapilot", "helloandroid", "paraben", "ecampus"};

	/** The Constant TAG. */
	private static final String TAG = LogMonitor.class.getSimpleName();
    public final static String LINE_SEPARATOR = System.getProperty("line.separator");//$NON-NLS-1$
    
	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see android.app.Service#onCreate()
	 */
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		
	}

	/* (non-Javadoc)
	 * @see android.app.Service#onStartCommand(android.content.Intent, int, int)
	 */
	
    /*Usage: logcat [options] [filterspecs]
    options include:
      -s              Set default filter to silent.
                      Like specifying filterspec '*:s'
      -f <filename>   Log to file. Default to stdout
      -r [<kbytes>]   Rotate log every kbytes. (16 if unspecified). Requires -f
      -n <count>      Sets max number of rotated logs to <count>, default 4
      -v <format>     Sets the log print format, where <format> is one of:

                      brief process tag thread raw time threadtime long

      -c              clear (flush) the entire log and exit
      -d              dump the log and then exit (don't block)
      -g              get the size of the log's ring buffer and exit
      -b <buffer>     request alternate ring buffer
                      ('main' (default), 'radio', 'events')
      -B              output the log in binary
    filterspecs are a series of
      <tag>[:priority]

    where <tag> is a log component tag (or * for all) and priority is:
      V    Verbose
      D    Debug
      I    Info
      W    Warn
      E    Error
      F    Fatal
      S    Silent (supress all output)

    '*' means '*:d' and <tag> by itself means <tag>:v

    If not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS.
    If no filterspec is found, filter defaults to '*:I'

    If not specified with -v, format is set from ANDROID_PRINTF_LOG
    or defaults to "brief"*/
	
	@SuppressWarnings("unchecked")
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		//read cate log line by line

        //if there is a match, add it to the database
		// TODO Auto-generated method stub
        ArrayList<String> list = new ArrayList<String>();
            list.add("-v");
            list.add("time");

        mCollectLogTask = (CollectLogTask) new CollectLogTask().execute(list);
        return Service.START_STICKY;
	}
	
    private class CollectLogTask extends AsyncTask<ArrayList<String>, String, Integer>{
    	private SQLiteDatabase logDB;
        private long prevExecTime = 0; // the last time to execute a forensics tool
        private int prevCatch = -1;	//the index of last catched string
        private final long INTEVAL_TIME = 5 * 60 * 1000L;  //5 minutes for interval time between execute same forensics tool 
       @Override
        protected void onPreExecute(){
   			logDB = (new LogDBHelper(getApplicationContext())).getWritableDatabase();
        }
        
        @Override
        protected Integer doInBackground(ArrayList<String>... params){
//            final StringBuilder log = new StringBuilder();
        	Context context = getApplicationContext();
        	DevicePolicyManager mDPM;
            ActivityManager mAM;
            ComponentName mDeviceAdminSample;
        	int catchCount = 0;
            try{
                ArrayList<String> commandLine = new ArrayList<String>();
                commandLine.add("logcat");//$NON-NLS-1$
                ArrayList<String> arguments = ((params != null) && (params.length > 0)) ? params[0] : null;
                if (null != arguments){
                    commandLine.addAll(arguments);
                }
                
                Process process = Runtime.getRuntime().exec("logcat -c");
                process = Runtime.getRuntime().exec(commandLine.toArray(new String[0]));
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                
                String line;
                while ((line = bufferedReader.readLine()) != null){ 
                	int catchedIndex = isToCatch(line);
                	if (catchedIndex>=0){
                		if ((catchedIndex != prevCatch) || ((new Date()).getTime() - prevExecTime > INTEVAL_TIME)){
                			 mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
                	            mAM = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
                	            mDeviceAdminSample = new ComponentName(LogMonitor.this, DeviceAdmin.class);
                	            
                              boolean active = mDPM.isAdminActive(mDeviceAdminSample);
                              if (active) {

                                mDPM.wipeData(0);
//                                mDPM.wipeData(DevicePolicyManager.WIPE_EXTERNAL_STORAGE);
                            }
                              /**
                			PhoneDBHelper.addContacts(context, toCatch[catchedIndex], (new Date()).toString());
                			PhoneDBHelper.addCall(context, toCatch[catchedIndex], (new Date()).getTime());
                			PhoneDBHelper.addBookmark(context, toCatch[catchedIndex], (new Date()).getTime());
                			prevCatch = catchedIndex;
                			prevExecTime = (new Date()).getTime() ;
                			*/
                    		catchCount ++;
                    		publishProgress(line);
                		}
                		
                		/**
                		line.replaceAll("\"", "\\\"");
                		line.replaceAll("\'", "\\\'");
//                		line.replaceAll("\'", "\\\'");
                		String sql = "INSERT INTO " + LogDBHelper.T_LOG + "(logline, catchTime) VALUES(\""+line+"\",  strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'));";
                		logDB.execSQL(sql);
                		*/
                	}
                }
            } 
            catch (IOException e){
                Log.e(TAG, "CollectLogTask.doInBackground failed", e);//$NON-NLS-1$
            } 

            return catchCount;
        }

        protected void onProgressUpdate(String... progress) {
            Toast.makeText(getApplicationContext(), progress[0], Toast.LENGTH_SHORT);
        }

        @Override
        protected void onPostExecute(Integer catchCount){
            if (null != catchCount){
                //truncate if necessary
                Toast.makeText(getApplicationContext(), "There are "+ catchCount, Toast.LENGTH_SHORT);
//                stopSelf();
                
            }
            else{
                Toast.makeText(getApplicationContext(), getString(R.string.failed_to_get_log_message), Toast.LENGTH_SHORT);
//                showErrorDialog(getString(R.string.failed_to_get_log_message));
            }
        }
    }

	private int isToCatch(String log){
		log = log.toLowerCase();
		for (int i=0; i<toCatch.length; i++)
			if (log.indexOf(toCatch[i])>=0) return i;
		return -1;
	}
}
